{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:11.988430Z",
     "start_time": "2025-01-20T11:25:11.980441Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.113016Z",
     "start_time": "2025-01-20T11:25:12.047950Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.120222Z",
     "start_time": "2025-01-20T11:25:12.115022Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ") # 对每个通道进行标准化"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.128721Z",
     "start_time": "2025-01-20T11:25:12.121226Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 6
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.153573Z",
     "start_time": "2025-01-20T11:25:12.130740Z"
    }
   },
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))\n",
    "        x = self.flatten(x)\n",
    "        x = act(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.171065Z",
     "start_time": "2025-01-20T11:25:12.154580Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "count_parameters(CNN())"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "435306"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:12.795768Z",
     "start_time": "2025-01-20T11:25:12.173107Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 9
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:24.518177Z",
     "start_time": "2025-01-20T11:25:12.801271Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 10
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:24.524811Z",
     "start_time": "2025-01-20T11:25:24.519180Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 11
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:25:24.533442Z",
     "start_time": "2025-01-20T11:25:24.527811Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:44:14.401126Z",
     "start_time": "2025-01-20T11:25:24.534446Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"selu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/cnn-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/cnn-{activation}\", save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=1000\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "33af727945504011910883d56bfa5673"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 10 / global_step 18000\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:45:17.257904Z",
     "start_time": "2025-01-20T11:45:17.023480Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 16
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-20T11:45:44.782564Z",
     "start_time": "2025-01-20T11:45:32.401940Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/cnn-{activation}/best.ckpt\",weights_only=True, map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.2565\n",
      "accuracy: 0.9125\n"
     ]
    }
   ],
   "execution_count": 17
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
